package com.act.moudles.act.service.impl;


import com.act.constant.TaskAnoTypeEnums;
import com.act.moudles.act.dao.ActDeployDao;
import com.act.moudles.act.service.ActDeployService;
import com.act.moudles.baseAct.entity.TaskAno;
import org.activiti.bpmn.model.*;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentBuilder;
import org.activiti.engine.repository.ProcessDefinition;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.FileInputStream;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ActDeployServiceImpl implements ActDeployService {

    @Resource
    private ActDeployDao actDeployDao;


    /**
     * 仓储服务，用于管理流程仓库，例如：部署，删除，读取流程资源
     * 可以用来部署我们的流程图，还可以创建我们的流程部署查询对象，用于查询刚刚部署的流程列表，便于我们管理流程
     */
    @Resource
    private RepositoryService repositoryService;

    @Override
    public Map<String,String> digDeploy(String bpmnPath, String pngPath, String bpmnName, String tentId)throws Exception {
        DeploymentBuilder deployment = repositoryService.createDeployment();
        deployment.addInputStream(bpmnName+".bpmn",new FileInputStream(bpmnPath));
        deployment.addInputStream(bpmnName+".png",new FileInputStream(pngPath));
        deployment.tenantId(tentId);
        Deployment ment  = deployment.deploy();
        //查询定义信息
        Map<String,String>  map = actDeployDao.selectProcdefByDepId(ment.getId());
        map.put("depName",ment.getName());
        return map;
    }

    @Override
    public List<TaskAno> anlTaskAnoByFlow(String flowKey, String tenantId) {
        //获取到流程连线
        ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey(flowKey)
                .processDefinitionTenantId(tenantId)
                .latestVersion()
                .singleResult();
        BpmnModel model = repositoryService.getBpmnModel(pd.getId());
        org.activiti.bpmn.model.Process process = model.getProcesses().get(0);
        Collection<FlowElement> flowElements = process.getFlowElements();
        Map<String,FlowElement>  idMap = new HashMap<String,FlowElement>(){{
            flowElements.forEach(o->{
                put(o.getId(),o);
            });
        }};

        //1读取不同类型
        List<SequenceFlow> sequenceFlowList = new ArrayList<>();
        for(FlowElement f : flowElements){
            if(f instanceof SequenceFlow  ){
                sequenceFlowList.add((SequenceFlow) f);
            }
        }
        //2.构建连线
        Map<String,List<String>>  linkedMap = new LinkedHashMap<>();
        for(SequenceFlow s : sequenceFlowList){
            String sourceId = s.getSourceRef();
            List<String>  targetIdList = linkedMap.get(sourceId);
            if(CollectionUtils.isEmpty(targetIdList)){
                targetIdList = new ArrayList<>();
            }
             targetIdList.add(s.getTargetRef());
            linkedMap.put(sourceId,targetIdList);
        }

        //3.构建对象
        List<TaskAno> taskAnos = new ArrayList<>();
        int index = 0;
        for(Map.Entry<String,List<String>> e : linkedMap.entrySet()){
            if(index == 0){
                FlowElement f = idMap.get(e.getKey());
                taskAnos.add(TaskAno.builder()
                             .taskName(getFlowType(f))
                             .taskType(getFlowType(f))
                             .tenantId(tenantId)
                             .taskSort(index)
                             .sid(f.getId())
                             .build())  ;
            }else {
                for(String  id : e.getValue()){
                    FlowElement f = idMap.get(id);
                    taskAnos.add(TaskAno.builder()
                                 .taskName(StringUtils.isEmpty(f.getName())?getFlowType(f): f.getName())
                                 .taskType(getFlowType(f))
                                 .tenantId(tenantId)
                                 .taskSort(index)
                                  .sid(f.getId())
                                 .build())   ;
                }
            }
            index++;
        }
        taskAnos = taskAnos.stream().collect(Collectors.collectingAndThen
                (Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing
                        (TaskAno::getSid))), ArrayList::new));
        return taskAnos;
    }


    /**
     * 获取到任务状态
     * @param f
     * @return
     */
    public String getFlowType(FlowElement f ){
        if(f instanceof  StartEvent){
            return TaskAnoTypeEnums.START.getTaskType();
        }else if(f  instanceof  EndEvent){
            return  TaskAnoTypeEnums.END.getTaskType();
        }else if(f instanceof  UserTask){
            return TaskAnoTypeEnums.USER_TASK.getTaskType();
        }else {
            return TaskAnoTypeEnums.OTHER.getTaskType();
        }

    }








}
